#include <map>

#include "GraphData.cuh"
#include "cuda/cuda_utils.cuh"

void GraphData::reorder(int *src_list, int *dst_list, int *reorder_map, const int nvertex, const int nedge, const bool dim)
{
  struct node_t{
    int n; 
    int deg;
    node_t(): n(0), deg(0){}
  };

  std::vector<node_t> odeg(nvertex);
  for (int i=0; i<nedge; i++)
  {
    int ind = dim ? src_list[i] : dst_list[i];
    odeg[ind].n = ind;
    ++odeg[ind].deg;
  }
  sort(odeg.begin(), odeg.end(), [](const node_t& a, const node_t& b)->bool { return a.deg < b.deg;});
  for (int i=0; i<nvertex; ++i)
  {
    reorder_map[i] = odeg[i].n;
    odeg[i].deg = i;
  }
  sort(odeg.begin(), odeg.end(), [](const node_t& a, const node_t& b)->bool { return a.n < b.n;});
  for (int i=0; i<nedge; ++i)
  {
      src_list[i] = odeg[src_list[i]].deg;
      dst_list[i] = odeg[dst_list[i]].deg;
  }
}

bool GraphData::check_directed(int* src_list, int *dst_list, size_t num_e) {
  struct edge_t {
    int s, d;
    inline size_t key(size_t root) const { return (size_t)d*root + s; }
  };
  std::map<size_t, edge_t> cache;
  for (int i=0; i<num_e; i++) {
    edge_t e{src_list[i], dst_list[i]};
    auto key = e.key(num_e);
    auto insert_ret = cache.insert({key, e});
    if (!insert_ret.second && cache[key].s == e.d && cache[key].s == e.d)
      cache.erase(key);
  }
  return cache.size() > 0;
}
